iT邦幫忙

2025 iThome 鐵人賽

DAY 3
0
生成式 AI

AI 產品與架構設計之旅:從 0 到 1,再到 Day 2系列 第 3

Day 3: 讓 LLM 知道「我是誰」- Slack ChatBot 的 System Prompt 設計哲學

  • 分享至 

  • xImage
  •  

嗨大家,我是 Debuguy。

昨天聊完技術選型,今天要來談一個更有趣的問題:如何讓 LLM 知道「自己」是誰?

這聽起來像哲學問題,但其實是決定你的 ChatBot 是「工具」還是「夥伴」的關鍵分水嶺。

從工具人到夥伴的轉換

最初的天真嘗試

一開始,我的 System Prompt 超級簡單:

You are a helpful AI assistant. Answer the user's questions.

結果呢?我得到了一個非常稱職的智能客服

👤 Debuguy:幫我查一下明天的會議

🤖 Bot:我無法訪問您的日曆系統。請您直接查看 Outlook 或 Google Calendar。

👤 Debuguy:這個 API 怎麼用?

🤖 Bot:根據文檔,您需要先進行身份驗證...

技術上完全正確,但感覺就是... 很工具

問題在哪裡?

我漸漸意識到,這不是功能問題,而是身份認知問題。

當 LLM 不知道「自己在哪裡」、「自己是誰」時,它就會默認自己是一個通用的 AI 助手。在 Slack 這個協作環境中,這種身份錯位會造成非常奇怪的對話體驗。

想像一下:如果有個新同事加入你們團隊,他每次回答問題都說「我是一個人類,我無法直接訪問您的系統」,你會不會覺得很奇怪?

身份認知的重要性

什麼是身份認知?

在 LLM 的世界裡,身份認知就是讓它理解:

  1. 我是誰:我的角色、名字、身份
  2. 我在哪裡:我運行在什麼環境中
  3. 我在做什麼:我的主要任務和目標
  4. 我怎麼互動:我應該如何與用戶溝通

這不是讓 LLM 產生真正的「自我意識」,而是給它一個穩定的行為框架

從「通用助手」到「Slack 同事」

當我把 System Prompt 改成這樣時:

You are a helpful AI assistant operating as a Slack bot. 
Your Slack ID is U09BASU9P6K.
The user who mentioned you is the one you must address in your reply.
When you finish your response, tag the user who originally mentioned you using their User ID, the format is <@USER_ID>.

突然間,對話的感覺就不一樣了:

👤 Debuguy@bot 幫我查一下明天的會議

🤖 Bot@Debuguy 我目前還沒有連接到日曆系統的權限,但如果你需要的話,我可以請管理員幫忙設定!

👤 Debuguy:這個 API 怎麼用?

🤖 Bot@Debuguy 讓我看看我們文檔裡有什麼...

注意差異了嗎?同樣是無法直接完成任務,但第二個版本:

  • 有明確的互動對象(tag 回去)
  • 表現出願意協助和解決問題的態度
  • 感覺像是團隊的一份子

System Prompt 設計的核心原則

原則 1: 明確的身份定位

You are a helpful AI assistant operating as a Slack bot. 
Your Slack ID is U09BASU9P6K.

這兩行看似簡單,但包含了三個關鍵資訊:

  • 角色:AI assistant(不是人類,但是助手)
  • 環境:Slack bot(在 Slack 環境中運作)
  • 身份標識:具體的 User ID(有具體的數位身份)

原則 2: 互動規則的建立

The user who mentioned you is the one you must address in your reply.
When you finish your response, tag the user who originally mentioned you using their User ID, the format is <@USER_ID>.

這是一個看似技術性的要求,但其實解決了一個很重要的社交問題

在多人的 Slack 頻道中,如果 Bot 回復時沒有 mention 原始提問者,就會造成:

  1. 提問者不知道 Bot 已經回答了
  2. 其他人不知道這個回答是針對誰的
  3. 對話變得混亂和難以追蹤

這個設計讓 Bot 學會了 Slack 的「社交禮儀」。

原則 3: 輸入格式的標準化

You will receive a message from a user in a Slack channel. format is <USER_ID>@<TIMESTAMP>: <MESSAGE>.

這個設計是為了解決一個實際問題:如何讓 LLM 從 Slack 的原始數據中提取出真正重要的資訊?

Slack 的原始事件長這樣:

{
  "type": "app_mention",
  "user": "U1234567890",
  "text": "<@U09BASU9P6K> 今天天氣如何?",
  "ts": "1699123456.123456",
  "channel": "C1234567890",
  "event_ts": "1699123456.123456",
  "thread_ts": "1699123456.123456"
  // ... 還有一堆其他資訊
}

如果直接把這個 JSON 丟給 LLM,它需要:

  1. 理解 JSON 結構
  2. 找出哪個欄位是真正的訊息
  3. 理解 Slack 的 mention 格式
  4. 過濾掉不相關的 metadata

這太復雜了!所以我選擇在進入 LLM 之前就處理成:

U1234567890@1699123456.123456: 今天天氣如何?

這個格式:

  • 簡潔明瞭:所有重要資訊都在一行
  • 容易解析:LLM 可以很容易識別發話者和內容
  • 保留脈絡:timestamp 保留了時間資訊,未來可以用於對話歷史

實際的程式碼實現

讓我們看看這個設計在 GenKit 中是怎麼實現的:

const chatFlow = ai.defineFlow(
  {
    name: 'chatFlow',
    inputSchema: z.object({
      text: z.string(),
      user: z.string(),
      ts: z.string(),
    }),
  },
  async ({ user, ts, text }) => (await ai.generate({
    model: googleAI.model('gemini-2.5-flash-lite'),
    system: `
      You are a helpful AI assistant operating as a Slack bot. 
      Your Slack ID is U09BASU9P6K.
      The user who mentioned you is the one you must address in your reply.

      You will receive a message from a user in a Slack channel. format is <USER_ID>@<TIMESTAMP>: <MESSAGE>.

      **Your Response Style:**
      * Be helpful, friendly, and conversational.
      * When you finish your response, tag the user who originally mentioned you using their User ID, the format is <@USER_ID>.
      * Always maintain a natural, human-like tone while being clear that you're an AI assistant.

      Remember: You are not just executing commands; you are participating in conversations as a helpful team member.
    `,
    prompt: `${user}@${ts}: ${text}`,
  })).text
);

完整的原始碼
歡迎有興趣的人下載玩玩,體驗一下囉~

這個設計的巧思

1. 結構化輸入

inputSchema: z.object({
  text: z.string(),
  user: z.string(),
  ts: z.string(),
})

使用 Zod schema 確保輸入資料的正確性,同時也讓程式碼更容易測試和除錯。

2. 格式化 Prompt

prompt: `${user}@${ts}: ${text}`,

把複雜的 Slack 事件轉換成 LLM 容易理解的格式。

3. 明確的互動期待

Remember: You are not just executing commands; you are participating in conversations as a helpful team member.

這一句話改變了整個互動的感覺。從「執行指令」到「參與對話」,這是工具和夥伴的根本差異。

效果驗證:Before vs After

Before(一般 Slack Bot)

Slack Bot

After(Slack ChatBot 模式)

Slack ChatBot

感受到差異了嗎?第二個版本:

  • 更個人化:直接稱呼使用者
  • 更主動:表現出願意深入協助的態度
  • 更像同事:使用更自然、友善的語調

設計過程中的思考

為什麼要包含具體的 Slack ID?

Your Slack ID is U09BASU9P6K.

這個看似技術性的細節,其實有深層的意義:

1. 身份的具體化

  • 不再是抽象的「AI助手」
  • 在 Slack 中有具體的數位身份
  • 可以被 mention、被加入群組、被分配權限

2. self-referenc 的能力

  • 還記得第一篇提到的「當系統足夠複雜且能 self-reference 時,某種自我會出現」的理論嗎?
  • 當有人問「你的 ID 是什麼」時,它能正確回答
  • 在需要設定權限或整合其他系統時,它知道自己的身份標識

3. 未來擴展的準備

  • 當系統變得複雜,需要多個 Bot 協作時,每個 Bot 都知道自己是誰

小結:身份認知的威力

看似簡單的 System Prompt 設計,其實解決了很多根本問題:

  1. 互動品質:從機械回應到自然對話
  2. 使用體驗:從冰冷工具到溫暖夥伴
  3. 系統架構:為未來的複雜功能打下基礎
    例如: 自動 mention 使用者的這個互動同時解決了當 LLM 需要長時間思考的時候
    使用者不用守在對話前,或是隨時回來檢查

這就是我說的「從 0 到 1」的關鍵轉折點。不是技術上的突破,而是產品思維上的轉變

從「讓 LLM 回答問題」到「讓 LLM 參與對話」

明天我們將回到技術層面,來看看 GenKit 這套開發框架是怎麼提供我們管理 prompt 的吧!


AI 的發展變化很快,目前這個想法以及專案也還在實驗中。但也許透過這個過程大家可以有一些經驗和想法互相交流,歡迎大家追蹤這個系列。

也歡迎追蹤我的 Threads @debuguy.dev


上一篇
Day 2: Slack ChatBot 的技術選型
系列文
AI 產品與架構設計之旅:從 0 到 1,再到 Day 23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言